home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C++ / Snippets / SuperSplash 1.0d1 / sources / •AZN_SUPER_SPLASH / AZN_TSuperSplash.cp next >
Text File  |  1995-10-20  |  14KB  |  595 lines

  1. /*    
  2. *    AZN_TSuperSplash.cp
  3. *
  4. *    Class implementation for 'TSuperSplash' class, a class
  5. *    to put up and manage a splash screen
  6. *    Inheritance:    BASE CLASS
  7. *
  8. *    © Andrew Nemeth  Warrimoo  Australia  1995
  9. *    aznemeng@zeta.org.au
  10. *
  11. *    File opened:        20 Jul 95
  12. *    File ammended:        20–23 Jul;
  13. *                    16, 22, 23, 25 Sep;
  14. *                    20 Oct 95
  15. */
  16.  
  17.  
  18.  
  19. #include    "AZN_TSuperSplash.h"                            //    put up & manage Splash screen
  20. #include    "JPEGUtilities.h"                                //    Aaron Giles JPEG utility package
  21.  
  22. #include    "AZN_DBUG.H"                                    //    debugging utilites
  23.  
  24. #include    <Quickdraw.h>
  25. #include    <Memory.h>                                    //    Mac 'TempXXXHandle()' traps
  26. #include    <Files.h>
  27. #include    <Aliases.h>
  28. #include    <Processes.h>
  29. #include    <Gestalt.h>
  30. #include    <LowMem.h>                                    //    Allows access to low mem globals
  31.  
  32.  
  33.  
  34.  
  35. //    FILE DEFINES
  36. //
  37. #define            kMoveToFront        (WindowPtr)-1L
  38. const OSType        kostypePICTtype    = 'PICT',
  39.                 kostypeJPEGtype    = 'JPEG';
  40.  
  41.  
  42.  
  43.  
  44. TSuperSplash::TSuperSplash ()
  45.  
  46.         :    f_OldGrafPort( NULL ),
  47.             f_ptrWind( NULL ),
  48.             f_hPict( NULL ),
  49.             f_shPictRes_ID( -1 ),
  50.             f_boolBigImg( FALSE )
  51. {
  52.     f_str63FileName[0] = 0;
  53. }
  54.  
  55.  
  56.  
  57. TSuperSplash::TSuperSplash ( const short shPictRes_ID )
  58.  
  59.         :    f_OldGrafPort( NULL ),
  60.             f_ptrWind( NULL ),
  61.             f_hPict( NULL ),
  62.             f_shPictRes_ID( shPictRes_ID ),
  63.             f_boolBigImg( FALSE )
  64. //
  65. //    Construct with PICT resource ID
  66. //
  67. {
  68.     f_str63FileName[0] = 0;
  69. }
  70.  
  71.  
  72.  
  73. TSuperSplash::TSuperSplash ( ConstStr63Param str63Name )
  74.  
  75.         :    f_OldGrafPort( NULL ),
  76.             f_ptrWind( NULL ),
  77.             f_hPict( NULL ),
  78.             f_shPictRes_ID( -1 ),
  79.             f_boolBigImg( FALSE )
  80. //
  81. //    Construct with filename
  82. //
  83. {
  84.     ASSERT( NULL != str63Name );
  85.  
  86.     ::BlockMoveData( (StringPtr)str63Name, f_str63FileName, str63Name[0] + 1 );
  87. }
  88.  
  89.  
  90.  
  91. TSuperSplash::~TSuperSplash ()
  92. //
  93. //    Destruct by getting rid of window
  94. //
  95. {
  96.     killSplash();
  97. }
  98.  
  99.  
  100.  
  101. Boolean                TSuperSplash::showSplash ( void )
  102. //
  103. //    Put up splash according to if
  104. //    1.    PICT res ID given or...
  105. //    2.    Graphics filename in home directory given
  106. //
  107. {
  108.     FSSpec        fsspecFile     = { 0, 0L, "\p" };
  109.     OSErr        myErr         = noErr;
  110.  
  111. //                                                        idiot filters
  112.     ASSERT( f_shPictRes_ID > 0 || f_str63FileName[0] > 0 );    
  113. //                                                        using PICT res ID
  114.     if ( f_shPictRes_ID > 0 )
  115.         {
  116.         f_hPict = ::GetPicture( f_shPictRes_ID );
  117.         if ( f_hPict )
  118.             {
  119. //                                                        pry PICT free of resource map!
  120.             ::DetachResource( (Handle)f_hPict );
  121.  
  122.             drawSplash( f_hPict );
  123.             return( TRUE );
  124.             
  125.             //    N.B.  No need to dispose of PicHandle here as 
  126.             //    it is disposed when 'killWindow()' is called
  127.             }
  128.         }
  129. //                                                        using filename
  130.     else if ( f_str63FileName[0] > 0 )
  131.         {
  132.         if ( noErr == grabNamedFile( f_str63FileName, &fsspecFile ) )
  133.             return( showSplash( fsspecFile ) );
  134.         }
  135.  
  136.     return( FALSE );
  137. }
  138.  
  139.  
  140.  
  141.  
  142. Boolean                TSuperSplash::showSplash ( const FSSpec & fsspecFile )
  143. //
  144. //    Given the FSSpec of a PICT or JPEG file
  145. //    extract image from data fork,
  146. //    load it into a PicHandle,
  147. //    assign to class var 'f_hPict'
  148. //    and then put up splash
  149. //
  150. {
  151.     OSErr        myErr         = noErr;
  152.  
  153. //                                                        get rid of any existing
  154.     killSplash();
  155.  
  156.     if ( noErr == grabPictHandleFromFile( fsspecFile, &f_hPict ) )
  157.         {
  158.         drawSplash( f_hPict );
  159.         return( TRUE );
  160.         }
  161.  
  162.     return( FALSE );
  163. }
  164.  
  165.  
  166.  
  167. void                    TSuperSplash::killSplash ( void )
  168. //
  169. //    Zap PicHandle, window & restore GrafPort
  170. //
  171. {
  172.     if ( f_hPict )
  173.         ::DisposeHandle( (Handle)f_hPict );
  174.     if ( f_ptrWind )
  175.         ::DisposeWindow( f_ptrWind );
  176.     if ( f_OldGrafPort )
  177.         ::SetPort( f_OldGrafPort );
  178.  
  179.     f_hPict = NULL;
  180.     f_ptrWind = f_OldGrafPort = NULL;
  181. }
  182.  
  183.  
  184.  
  185. void                    TSuperSplash::drawSplash ( PicHandle hSplashPICT )
  186. //
  187. //    Given a PicHandle, create window & get splash on screen
  188. //    N.B.  ASSUMES 'PicHandle' is a free-standing handle
  189. //    and not part of a resource map!  This is because
  190. //    'DisposeHandle()' is called if something goes wrong!!!
  191. //
  192. {
  193.     const Str31    kstr31_Prompt        = { "\pLoading image…" };
  194.     const short    kshWindowKind         = altDBoxProc,
  195.                 kshBlackPattern    = 1;
  196.  
  197.     Pattern        recPattern;
  198.     Rect            rectPICT             = { 0, 0, 10, 10 };
  199.  
  200. //                                                        idiot filters
  201.     ASSERT( NULL != hSplashPICT );
  202.     ASSERT( NULL == f_ptrWind );
  203.     ASSERT( NULL == f_OldGrafPort );
  204. //                                                        save current GrafPort
  205.     ::GetPort( &f_OldGrafPort );
  206.     ::SetCursor( *GetCursor(watchCursor) );
  207. //                                                        create window
  208.     if ( hasColourQD() )
  209.         f_ptrWind = ::NewCWindow( NULL, &rectPICT, NULL, FALSE, kshWindowKind,
  210.                                 kMoveToFront, FALSE, 0L );
  211.     else
  212.         f_ptrWind = ::NewWindow( NULL, &rectPICT, NULL, FALSE, kshWindowKind,
  213.                             kMoveToFront, FALSE, 0L );
  214. //                                                        return if new window failed
  215.     if ( NULL == f_ptrWind )
  216.         return;
  217. //                                                        size the window so PICT will fit!
  218.     f_ptrWind->portRect = (**(hSplashPICT)).picFrame;
  219. //                                                        place window in ALRT position
  220.     centreWindow( f_ptrWind, TRUE );
  221. //                                                        assign where to draw the pict!
  222.     rectPICT = f_ptrWind->portRect;
  223. //                                                        grab a pattern from system
  224.     ::GetIndPattern( &recPattern, sysPatListID, kshBlackPattern );
  225.     
  226.     //    Why do it this way?  Because we can then access
  227.     //    *all* the system patterns, not just those held
  228.     //    in the Quickdraw global 'qd'.
  229.  
  230. //                                                        get window on screen
  231.     ::SetPort( f_ptrWind );
  232.     ::ShowWindow( f_ptrWind );
  233.  
  234.     ::BeginUpdate( f_ptrWind );
  235.         if ( f_boolBigImg )
  236.             {
  237. //                                                        fill window with system pattern
  238.             ::FillRect( &(f_ptrWind->portRect), &recPattern );
  239. //                                                        put prompt in top LHS
  240.             ::MoveTo( rectPICT.left+10, rectPICT.top+15 );
  241.             ::TextSize( 9 );
  242.             ::TextMode( notSrcCopy );
  243.             ::DrawString( kstr31_Prompt ); 
  244.             ::PenNormal();
  245.             }
  246. //                                                        draw PICT
  247.         ::DrawPicture( hSplashPICT, &rectPICT );
  248.  
  249.     ::EndUpdate( f_ptrWind );
  250.  
  251.     ::SetCursor( &qd.arrow );
  252. }
  253.  
  254.  
  255.  
  256.  
  257. OSErr                TSuperSplash::grabNamedFile ( ConstStr63Param     str63Name, 
  258.                                             FSSpecPtr         ptrfsspecFile )
  259. //
  260. //    1.    Grabs file with name matching that in 'str63Name'
  261. //    2.    Looks in current app's 'home' directory only!
  262. //    3.    Resolves an alias (if necessary)
  263. //    4.    Loads FSSpec into ptr provided & returns OSErr
  264. //
  265. {
  266.     const Boolean    kboolResolveAliasChains = TRUE;
  267.  
  268.     FSSpec            fsspecDummy = { 0, 0L, "\p" };
  269.     Boolean            boolIsFolder = FALSE,
  270.                     boolWasAlias = FALSE;
  271.     short            shVRefNum = 0;
  272.     long                lgParID = 0;
  273.     OSErr            myErr = noErr;
  274.  
  275. //                                                        idiot filters
  276.     ASSERT( NULL != ptrfsspecFile );
  277.     ASSERT( str63Name[0] > 0 );
  278. //                                                        grab 'home directory' co-ords
  279.     myErr = grabVol_ParId( &shVRefNum, &lgParID );
  280. //                                                        create FSSpec for target file
  281.     if ( noErr == myErr )
  282.         myErr = ::FSMakeFSSpec( shVRefNum, lgParID, str63Name,
  283.                             &fsspecDummy );
  284. //                                                        resolve alias (if necessary)
  285.     if ( noErr == myErr )
  286.         {
  287.         myErr = ::ResolveAliasFile( &fsspecDummy, kboolResolveAliasChains,
  288.                                 &boolIsFolder, &boolWasAlias );;
  289.         if ( noErr == myErr && boolIsFolder )
  290.             myErr = fnfErr;
  291.         }
  292. //                                                        assign result only if file exists! (noErr)
  293.     if ( noErr == myErr )
  294.         ::BlockMoveData( &fsspecDummy, ptrfsspecFile, sizeof( FSSpec ) );
  295.  
  296.     return( myErr );
  297. }
  298.  
  299.  
  300.  
  301.  
  302. OSErr                TSuperSplash::grabVol_ParId ( short * ptrshVol, long * ptrlgParID )
  303. //
  304. //    Grab the 'vRefNum' & 'parID' of the
  305. //    currently running application (ie. the 'HOME' dir)
  306. //
  307. {
  308.     ProcessSerialNumber        psnCurrent;
  309.     ProcessInfoRec         procirRec;
  310.     FSSpec                fsspecDummy;
  311.     OSErr                myErr = noErr;
  312.  
  313. //                                                        idiot filters
  314.     ASSERT( NULL != ptrshVol );
  315.     ASSERT( NULL != ptrlgParID );
  316. //                                                        grab PSN of current process
  317.     myErr = ::GetCurrentProcess( &psnCurrent );    
  318. //                                                        now grab its details
  319.     if ( noErr == myErr )
  320.         {
  321.         procirRec.processInfoLength = sizeof( ProcessInfoRec );
  322.         procirRec.processName = NULL;
  323.         procirRec.processAppSpec = &fsspecDummy;
  324.         
  325.         myErr = ::GetProcessInformation( &psnCurrent, &procirRec );
  326.         }
  327. //                                                        assign values
  328.     if ( noErr == myErr )
  329.         {
  330.         *ptrshVol = fsspecDummy.vRefNum;
  331.         *ptrlgParID = fsspecDummy.parID;
  332.         }
  333.  
  334.     return( myErr );
  335. }
  336.  
  337.  
  338.  
  339.  
  340. OSErr                TSuperSplash::grabPictHandleFromFile ( const FSSpec &     fsspecFile, 
  341.                                                     PicHandle         * ptrPictHandle )
  342. //
  343. //    Given a PICT or JPEG type file, extract the data
  344. //    from the data fork, create a handle and dump data
  345. //    in as PICT handle.
  346. //
  347. //    Because image could be any size, we use 
  348. //    System Heap Temporary Memory.
  349. //
  350. {
  351.     enum            EFileType{ kshIsPICT, kshIsJPEG, kshInvalid };
  352.     const long    klgPICT_Header     = 512L;
  353.  
  354.     EFileType        enumFType;
  355.     long            lgHandleSize         = 0L;
  356.     short        shRefNum             = -1;
  357.     Handle        hData             = NULL;
  358.     OSErr        myErr             = noErr;
  359.  
  360. //                                                        idiot filter
  361.     ASSERT( NULL != ptrPictHandle );
  362.  
  363.     *ptrPictHandle = NULL;
  364. //                                                        reset 'large img' flag
  365.     f_boolBigImg = FALSE;
  366.  
  367.     //    Examine file type
  368.     //
  369.     if ( isFileOfType( fsspecFile, kostypePICTtype ) )
  370.         enumFType = kshIsPICT;
  371.  
  372.     else if ( isFileOfType( fsspecFile, kostypeJPEGtype ) )
  373.         enumFType = kshIsJPEG;
  374.  
  375.     else
  376.         enumFType = kshInvalid;
  377.  
  378.  
  379.     //    Process file according to type
  380.     //
  381.     switch ( enumFType )
  382.         {
  383.         case kshIsPICT:
  384. //                                                        open data fork of file
  385.             myErr = ::FSpOpenDF( (FSSpecPtr)&fsspecFile, 
  386.                             fsRdPerm, 
  387.                             &shRefNum );
  388. //                                                        figure size of PICT
  389.             if ( noErr == myErr )
  390.                 myErr = ::GetEOF( shRefNum, &lgHandleSize );
  391.         
  392.             if ( noErr == myErr )
  393.                 myErr = ( lgHandleSize > klgPICT_Header ) ? noErr : eofErr;
  394. //                                                        create handle to hold pict
  395.             if ( noErr == myErr )
  396.                 {
  397.                 //    PicHandle size is size of data fork, less
  398.                 //    the PICT header ('klgPICT_Header').
  399.                 //
  400.                 lgHandleSize -= klgPICT_Header;
  401. //                                                        allocate handle on SYSTEM heap!
  402.                 if ( ::TempFreeMem() > lgHandleSize )
  403.                     {
  404.                     *ptrPictHandle = (PicHandle)::TempNewHandle( lgHandleSize, &myErr );
  405.                     //
  406.                     //    Some notes about this.  With System 6, to dispose you would
  407.                     //    need to call '::TempDisposeHandle()', but with system 7 
  408.                     //    '::DisposeHandle()' works just as well
  409.                     //
  410.                     //    See Think Reference entry on 'About Temporary Memory'
  411.                     //
  412.                     if ( NULL == *ptrPictHandle )
  413.                         myErr = memFullErr;
  414.                     }
  415.                 else
  416.                     myErr = memFullErr;
  417.                 }
  418. //                                                        now read data into PicHandle
  419.             if ( noErr == myErr )
  420.                 {
  421.                 ::SetFPos( shRefNum, fsFromStart, klgPICT_Header );
  422. //                                                        lock as 'FSRead' can move memory
  423.                 ::HLock( (Handle)*ptrPictHandle ); 
  424.         
  425.                 myErr = ::FSRead( shRefNum, &lgHandleSize, (Ptr)**ptrPictHandle );
  426.         
  427.                 ::HUnlock( (Handle)*ptrPictHandle );
  428.                 }
  429.             break;
  430.  
  431.  
  432.         case kshIsJPEG:
  433. //                                                        need Quicktime for JPEG
  434.             if ( quicktimeAvailable() )
  435.                 {
  436.                 myErr = ::FSpOpenDF( (FSSpecPtr)&fsspecFile, 
  437.                                 fsRdPerm, 
  438.                                 &shRefNum );
  439. //                                                        figure size of image
  440.                 if ( noErr == myErr )
  441.                     myErr = ::GetEOF( shRefNum, &lgHandleSize );
  442.             
  443.                 if ( noErr == myErr )
  444.                     myErr = ( lgHandleSize > 0L ) ? noErr : eofErr;
  445. //                                                        create handle to hold image
  446.                 if ( noErr == myErr )
  447.                     {
  448.                     if ( ::TempFreeMem() > lgHandleSize )
  449.                         {
  450.                         hData = ::TempNewHandle( lgHandleSize, &myErr );
  451.                         if ( NULL == hData )
  452.                             myErr = memFullErr;
  453.                         }
  454.                     else
  455.                         myErr = memFullErr;
  456.                     }
  457. //                                                        now read data into handle
  458.                 if ( noErr == myErr )
  459.                     {
  460.                     ::HLock( hData ); 
  461.                     myErr = ::FSRead( shRefNum, &lgHandleSize, (Ptr)*hData );
  462.                     ::HUnlock( hData );
  463.                     }
  464. //                                                        convert JPEG data to PICT
  465.                 if ( noErr == myErr && lgHandleSize > 0L )
  466.                     {
  467.                     *ptrPictHandle = (PicHandle)::WrapJPEG( hData );
  468.  
  469.                     f_boolBigImg = TRUE;
  470.                     }
  471.                 }
  472.             else
  473.                 myErr = fnfErr;
  474.  
  475.             break;
  476.  
  477.  
  478.         case kshInvalid:
  479.             myErr = fnfErr;
  480.             break;
  481.         }
  482.  
  483.     return( myErr );
  484. }
  485.  
  486.  
  487.  
  488. Boolean                TSuperSplash::isFileOfType ( const FSSpec     & fsspecFile, 
  489.                                             const OSType     ostypeFile )
  490. //
  491. //    Is file of type 'ostypeFile'?
  492. //
  493. {
  494.     HFileInfo        finfoRec;
  495.     Boolean        boolResult = FALSE;
  496.     OSErr        myErr = noErr;
  497.  
  498. //                                                        idiot filter
  499.     ASSERT( ostypeFile > 0L );
  500. //                                                        set up block for cat. lookup
  501.     finfoRec.ioNamePtr     = (StringPtr)fsspecFile.name;
  502.     finfoRec.ioVRefNum     = fsspecFile.vRefNum;
  503.     finfoRec.ioDirID     = fsspecFile.parID;
  504.     finfoRec.ioFDirIndex = 0;
  505. //                                                        look up catalogue
  506.     myErr = ::PBGetCatInfoSync( (CInfoPBPtr)&finfoRec );
  507.     if ( noErr == myErr )
  508.         {
  509. //                                                        examing file (and not directories!)
  510.         if ( ( finfoRec.ioFlAttrib & ioDirMask ) == 0  )            
  511.             {
  512.             if ( ostypeFile == finfoRec.ioFlFndrInfo.fdType )
  513.                 boolResult = TRUE;
  514.             }
  515.         }
  516.  
  517.     return( boolResult );
  518. }
  519.  
  520.  
  521.  
  522. Boolean                TSuperSplash::hasColourQD ( void )
  523. //
  524. //    STATIC FUNCTION!
  525. //    Use gestalt to see if Colour QD is present
  526. //
  527. {
  528.     const long     klgGestaltMask = 1L;
  529.     long            lgFeature = 0L;
  530.     OSErr        myErr = noErr;
  531.  
  532.  
  533.     myErr = ::Gestalt( gestaltQuickdrawFeatures, &lgFeature );
  534.     if ( ( myErr == noErr ) && ( lgFeature & ( klgGestaltMask << gestaltHasColor ) ) )
  535.         return( TRUE );
  536.     else
  537.         return( FALSE );
  538. }
  539.  
  540.  
  541.  
  542. Boolean                TSuperSplash::quicktimeAvailable ( void )
  543. //
  544. //    Use Gestalt to see if Quicktime is available
  545. //    (Needed by JPEG code!)
  546. //
  547. //    Assume 'available' if Quicktime version > 2.0
  548. //
  549. {
  550.     const long     klgGestaltMask = 1L;
  551.     long            lgFeature = 0L;
  552.     OSErr        myErr = noErr;
  553.  
  554.  
  555.     myErr = ::Gestalt( gestaltQuickTimeVersion, &lgFeature );
  556.     if ( ( myErr == noErr ) && ( lgFeature >= 0x0200 ) )
  557.         return( TRUE );
  558.     else
  559.         return( FALSE );
  560. }
  561.  
  562.  
  563.  
  564. void                    TSuperSplash::centreWindow ( WindowPtr ptrWind, Boolean boolALRTpos )
  565. //
  566. //    Given a WindowPtr, centre it on screen (or
  567. //    place it in ALRT position).  Code always makes
  568. //    sure that new position never puts window 
  569. //    below the menuBar.
  570. //
  571. {
  572.     const short    kshMBarHeight         = LMGetMBarHeight(),
  573.                 kshScreen_Width     = qd.screenBits.bounds.right,
  574.                 kshScreen_Height     = qd.screenBits.bounds.bottom,
  575.                 kshPos             = boolALRTpos ? 3 : 2,
  576.                 kshVertMin         = kshMBarHeight + 2;
  577.  
  578.     Rect            rectWind;
  579.     short        x, y = 0;
  580.  
  581. //                                                        sanity check
  582.     if ( ptrWind == NULL )
  583.         return;
  584.     else
  585.         rectWind = ptrWind->portRect;    
  586. //                                                        calc new offsets
  587.     ::OffsetRect( &rectWind, -rectWind.left, -rectWind.top );
  588.     x = ( kshScreen_Width - rectWind.right ) / 2;
  589.     y = kshMBarHeight + ( ( kshScreen_Height - rectWind.bottom - kshMBarHeight ) / kshPos );
  590. //                                                        make sure window is always below mbar!
  591.     y = ( y < kshVertMin) ? kshVertMin : y;    
  592.  
  593.     ::MoveWindow( ptrWind, x, y, FALSE );
  594. }
  595.